package hbot;

import hbot.User32Access.User32AccessException;
import hbot.User32Access.WindowNotFoundException;

import java.awt.AWTException;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.awt.Rectangle;
import java.awt.image.ComponentColorModel;

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

public class ScreenReader {
	
	/** the window size of the Hearthstone window  */
	Rectangle m_WindowSize;
	
	/** contains the latest screenshot taken from the Hearthstone window */
	BufferedImage m_CurrentWindow;
	
	/** robot used to take the screenshots */
	Robot m_Robot;
	
	/**
	 * constructor - initializes this Class, gets hs window size etc.
	 * @throws User32AccessException 
	 * @throws WindowNotFoundException 
	 */
	public ScreenReader() throws WindowNotFoundException, User32AccessException{
		m_WindowSize = User32Access.getRect("Hearthstone");
		
		
		
		try {
			m_Robot = new Robot();
		} catch (AWTException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * takes a screenshot from the current Hearthstone window and stores it into m_CurrentWindow
	 */
	private void readScreen(){
		Rectangle windowRect = new Rectangle(m_WindowSize);
		m_CurrentWindow = m_Robot.createScreenCapture(windowRect);
	}
	
	/**
	 * takes a screenshot from the current Hearthstone window and returns it as OpenCV Mat
	 * @return
	 */
	public Mat getHearthstoneWindow(){
		this.readScreen();

	    byte[] data = convertBufferedImageToByteArray(m_CurrentWindow);

	    Mat mat = new Mat(m_CurrentWindow.getHeight(), m_CurrentWindow.getWidth(), CvType.CV_8UC4);
	    mat.put(0, 0, data);
		
	    Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGBA2BGR, 3);
	    
		return mat;
	}
	
	/**
	 * Creates a BufferedImage with appropriate color model for OpenCV
	 * @param w - width of the image
	 * @param h - height of the image
	 * @return A blank BufferedImage with appropriate color model for OpenCV conversion and Size w x h
	 */
	public static BufferedImage createBufferedImage(int w, int h){
		ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
		int[] nBits = {8, 8, 8, 8};
		ColorModel cm = new ComponentColorModel(cs, nBits, 
		                              			true, false,
		                              			Transparency.TRANSLUCENT, 
		                              			DataBuffer.TYPE_BYTE);
		
		SampleModel sm = cm.createCompatibleSampleModel(w, h);
		DataBufferByte db = new DataBufferByte(w*h*4); //4 channels buffer
		WritableRaster r = WritableRaster.createWritableRaster(sm, db, new Point(0,0));
		BufferedImage bm = new BufferedImage(cm,r,false,null);
		return bm;
	}

	/**
	 * Converts a BufferedImage to a byte array
	 * @param img - the image to convert
	 * @return byte array containing the img image data
	 */
	public static byte[] convertBufferedImageToByteArray(BufferedImage img){
		BufferedImage cvImg = createBufferedImage(img.getWidth(), img.getHeight());
		Graphics2D g = cvImg.createGraphics();
		g.drawImage(img, 0, 0, null);
		g.dispose();
		return ((DataBufferByte)cvImg.getRaster().getDataBuffer()).getData();
	}
}
